﻿/*
 * Netkill
 * 
 * Copyright © 2012 John Granström. All Rights Reserved.
 * 
 * This software is released under the terms and conditions of the BSD license. See 'license.txt' for details.'
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace Netkill
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Backbone backbone = new Backbone();
            Application.Run(backbone);
            backbone.Cleanup();
        }

        class Backbone : ApplicationContext
        {
            NotifyIcon notify = new NotifyIcon();

            Interfacer inter;
            Processor processor;

            Form1 form;

            public Backbone()
            {
                InitNotify();

                // Init system components
                inter = new Interfacer();
                processor = new Processor(FirstCriticalProcessStarted, LastCriticalProcessEnded);
                if (!processor.StartMon(Global.SavedMonString))
                    throw new Exception("Failed to initiate processor monitor.");

                // Show form on demand
                if (Global.ShowOnStartup)
                    showForm();
            }

            private void InitNotify()
            {
                MenuItem openItem = new MenuItem();
                openItem.Text = "&Open";
                openItem.Click += openItem_Click;

                MenuItem exitItem = new MenuItem();
                exitItem.Text = "E&xit";
                exitItem.Click += exitItem_Click;

                ContextMenu menu = new ContextMenu();
                menu.MenuItems.Add(openItem);
                menu.MenuItems.Add(exitItem);
                
                notify.Text = "Netkill";
                notify.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
                notify.ContextMenu = menu;
                notify.Visible = true;
                notify.DoubleClick += openItem_Click;
            }

            void openItem_Click(object sender, EventArgs e)
            {
                showForm();
            }

            private void showForm()
            {
                if (form == null)
                {
                    form = new Form1(inter, processor);
                    form.FormClosed += form_FormClosed;
                    form.Show();
                }
            }

            void form_FormClosed(object sender, FormClosedEventArgs e)
            {
                form = null;
            }

            void exitItem_Click(object sender, EventArgs e)
            {
                Application.Exit();
            }

            private void FirstCriticalProcessStarted()
            {
                if (form != null)
                    form.Invoke((Action)delegate() { form.BtnKill.Enabled = false; });
                inter.DisableLivingInterfaces();
                Thread.Sleep(500);
                if(form != null)
                    form.RefreshUI();
            }

            private void LastCriticalProcessEnded()
            {
                if(form != null)
                    form.Invoke((Action)delegate() { form.BtnRevive.Enabled = false; });
                inter.EnableLivingInterfaces();
                Thread.Sleep(2000); // Let's sleep a while on this thread to let the connection establish itself again
                if(form != null)
                    form.RefreshUI();
            }

            public void Cleanup()
            {
                notify.Visible = false;
                notify.Dispose();
                notify = null;

                // Cleanup system components
                processor.Stop();
                if (inter.IsKilled)
                    inter.EnableLivingInterfaces();
            }
        }
    }
}
